﻿using System;
using System.IO;
using System.Linq;
using PokemonBattle.PokemonData.Util;

namespace PokemonBattle.PokemonData
{
    public class PokemonCustomInfo : DataStream, ICloneable, IEquatable<PokemonCustomInfo>
    {

        public PokemonCustomInfo()
        {
            this.SelectedMoves = new string[] { "", "", "", "" };
            this.Ev = new Base6D(0);
            this.Iv = new Base6D(0);
        }

        #region props

        public PokemonCharacter Character { get; set; }
        public PokemonGender Gender { get; set; }
        public int Identity { get; set; }
        public Item Item { get; set; }
        public byte LV { get; set; }
        public string Nickname { get; set; }
        public string[] SelectedMoves { get; set; }
        public byte SelectedTrait { get; set; }

        #endregion

        #region 6D

        public Base6D Ev { get; set; }
        public Base6D Iv { get; set; }

        public byte HPEV
        {
            get { return (byte)Ev.Hp; }
            set { Ev.Hp = value; }
        }
        public byte AttackEV
        {
            get { return (byte)Ev.Atk; }
            set { Ev.Atk = value; }
        }
        public byte DefenceEV
        {
            get { return (byte)Ev.Def; }
            set { Ev.Def = value; }
        }
        public byte SpAttackEV
        {
            get { return (byte)Ev.SpAtk; }
            set { Ev.SpAtk = value; }
        }
        public byte SpDefenceEV
        {
            get { return (byte)Ev.SpDef; }
            set { Ev.SpDef = value; }
        }
        public byte SpeedEV
        {
            get { return (byte)Ev.Speed; }
            set { Ev.Speed = value; }
        }

        public byte HPIV
        {
            get { return (byte)Iv.Hp; }
            set { Iv.Hp = value; }
        }
        public byte AttackIV
        {
            get { return (byte)Iv.Atk; }
            set { Iv.Atk = value; }
        }
        public byte DefenceIV
        {
            get { return (byte)Iv.Def; }
            set { Iv.Def = value; }
        }
        public byte SpAttackIV
        {
            get { return (byte)Iv.SpAtk; }
            set { Iv.SpAtk = value; }
        }
        public byte SpDefenceIV
        {
            get { return (byte)Iv.SpDef; }
            set { Iv.SpDef = value; }
        }
        public byte SpeedIV
        {
            get { return (byte)Iv.Speed; }
            set { Iv.Speed = value; }
        }

        #endregion

        public void CheckData()
        {
            if (this.Iv.ValidateIv() == false) this.Iv.SetAll(31);
            if (this.Ev.ValidateEv() == false) this.Iv.SetAll(85);
        }

        #region abstract

        public override void Load(Stream input)
        {
            BinaryReader reader = new BinaryReader(input);
            this.Identity = reader.ReadInt32();
            if (this.Identity != 0)
            {
                this.Nickname = reader.ReadString();
                this.LV = reader.ReadByte();
                this.AttackEV = reader.ReadByte();
                this.DefenceEV = reader.ReadByte();
                this.SpeedEV = reader.ReadByte();
                this.SpAttackEV = reader.ReadByte();
                this.SpDefenceEV = reader.ReadByte();
                this.HPEV = reader.ReadByte();
                this.AttackIV = reader.ReadByte();
                this.DefenceIV = reader.ReadByte();
                this.SpeedIV = reader.ReadByte();
                this.SpAttackIV = reader.ReadByte();
                this.SpDefenceIV = reader.ReadByte();
                this.HPIV = reader.ReadByte();
                this.Gender = (PokemonGender)reader.ReadInt32();
                this.SelectedTrait = reader.ReadByte();
                this.Character = (PokemonCharacter)reader.ReadInt32();
                this.Item = (PokemonBattle.PokemonData.Item)reader.ReadInt32();
                for (int i = 0; i < 4; i++)
                {
                    this.SelectedMoves[i] = reader.ReadString();
                }
            }
        }

        public override void Save(Stream output)
        {
            BinaryWriter writer = new BinaryWriter(output);
            writer.Write(this.Identity);
            if (this.Identity != 0)
            {
                writer.Write(this.Nickname);
                writer.Write(this.LV);
                writer.Write(this.AttackEV);
                writer.Write(this.DefenceEV);
                writer.Write(this.SpeedEV);
                writer.Write(this.SpAttackEV);
                writer.Write(this.SpDefenceEV);
                writer.Write(this.HPEV);
                writer.Write(this.AttackIV);
                writer.Write(this.DefenceIV);
                writer.Write(this.SpeedIV);
                writer.Write(this.SpAttackIV);
                writer.Write(this.SpDefenceIV);
                writer.Write(this.HPIV);
                writer.Write((int)this.Gender);
                writer.Write(this.SelectedTrait);
                writer.Write((int)this.Character);
                writer.Write((int)this.Item);
                foreach (string str in this.SelectedMoves)
                {
                    writer.Write(str);
                }
            }
        }

        #endregion

        #region ICloneable

        public PokemonCustomInfo Clone()
        {
            PokemonCustomInfo info = this.MemberwiseClone() as PokemonCustomInfo;
            info.SelectedMoves = new string[4];
            for (int i = 0; i < 4; i++)
            {
                info.SelectedMoves[i] = SelectedMoves[i];
            }
            return info;
        }

        object ICloneable.Clone()
        {
            return this.Clone();
        }

        #endregion

        #region IEquatable

        public bool Equals(PokemonCustomInfo other)
        {
            return this.Identity == other.Identity &&
                this.Nickname == other.Nickname &&
                this.LV == other.LV &&
                this.HPEV == other.HPEV &&
                this.AttackEV == other.AttackEV &&
                this.DefenceEV == other.DefenceEV &&
                this.SpeedEV == other.SpeedEV &&
                this.SpAttackEV == other.SpAttackEV &&
                this.SpDefenceEV == other.SpDefenceEV &&
                this.HPIV == other.HPIV &&
                this.AttackIV == other.AttackIV &&
                this.DefenceIV == other.DefenceIV &&
                this.SpeedIV == other.SpeedIV &&
                this.SpAttackIV == other.SpAttackIV &&
                this.SpDefenceIV == other.SpDefenceIV &&
                this.Gender == other.Gender &&
                this.Character == other.Character &&
                this.SelectedTrait == other.SelectedTrait &&
                this.Item == other.Item &&
                this.SelectedMoves[0] == other.SelectedMoves[0] &&
                this.SelectedMoves[1] == other.SelectedMoves[1] &&
                this.SelectedMoves[2] == other.SelectedMoves[2] &&
                this.SelectedMoves[3] == other.SelectedMoves[3];
        }

        #endregion

        #region old

        public static PokemonCustomInfo FromStream(Stream input)
        {
            return FromStream<PokemonCustomInfo>(input);
        }

        /// <summary>
        /// Form From 不分
        /// </summary>
        public static PokemonCustomInfo FormStream(Stream input)
        {
            return FromStream<PokemonCustomInfo>(input);
        }

        #endregion
    }
}